package com.campus.counseling.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.campus.counseling.entity.Appointment;
import com.campus.counseling.entity.SysLoginLog;
import com.campus.counseling.entity.SysLoginStats;
import com.campus.counseling.entity.SysUser;
import com.campus.counseling.model.mapper.AppointmentMapper;
import com.campus.counseling.model.mapper.SysLoginLogMapper;
import com.campus.counseling.model.mapper.SysLoginStatsMapper;
import com.campus.counseling.model.mapper.SysUserMapper;
import com.campus.counseling.model.vo.LoginStatsVO;
import com.campus.counseling.model.vo.TimeDistributionVO;
import com.campus.counseling.model.vo.UserActiveVO;
import com.campus.counseling.service.LoginAnalysisService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class LoginAnalysisServiceImpl implements LoginAnalysisService {

    private final SysLoginLogMapper loginLogMapper;
    private final SysLoginStatsMapper loginStatsMapper;
    private final SysUserMapper userMapper;
    private final AppointmentMapper appointmentMapper;

    @Override
    public LoginStatsVO getLoginStats(LocalDate startDate, LocalDate endDate) {
        LoginStatsVO stats = new LoginStatsVO();
        
        // 1. 获取总用户数
        Long totalUsers = userMapper.selectCount(null);
        stats.setTotalUsers(totalUsers != null ? totalUsers.intValue() : 0);
        
        // 2. 获取今日预约数
        LocalDateTime todayStart = LocalDate.now().atStartOfDay();
        LocalDateTime todayEnd = LocalDate.now().atTime(23, 59, 59);
        Long todayAppointments = appointmentMapper.selectCount(new LambdaQueryWrapper<Appointment>()
            .between(Appointment::getAppointmentTime, todayStart, todayEnd));
        stats.setTodayAppointments(todayAppointments != null ? todayAppointments.intValue() : 0);
        
        // 3. 获取活跃用户数（今日登录的不同用户数）
        List<Map<String, Object>> activeUsersList = loginLogMapper.selectMaps(
            new LambdaQueryWrapper<SysLoginLog>()
                .select(SysLoginLog::getUserId)
                .between(SysLoginLog::getCreateTime, todayStart, todayEnd)
                .groupBy(SysLoginLog::getUserId)
        );
        stats.setActiveUsers(activeUsersList != null ? activeUsersList.size() : 0);
        
        // 4. 计算系统负载（CPU使用率）
        OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
        String systemLoad = String.format("%.1f%%", osBean.getSystemLoadAverage() * 100);
        stats.setSystemLoad(systemLoad);
        
        // 5. 获取登录统计数据
        Map<String, Object> loginStats = loginLogMapper.selectDailyStats(
            startDate.atStartOfDay(),
            endDate.atTime(23, 59, 59)
        );
        
        if (loginStats != null) {
            // 使用Optional和getOrDefault来安全地获取值
            stats.setTotalLogins(Optional.ofNullable(loginStats.get("login_count"))
                .map(num -> ((Number) num).intValue())
                .orElse(0));
                
            stats.setUniqueUsers(Optional.ofNullable(loginStats.get("unique_user_count"))
                .map(num -> ((Number) num).intValue())
                .orElse(0));
                
            stats.setSuccessCount(Optional.ofNullable(loginStats.get("success_count"))
                .map(num -> ((Number) num).intValue())
                .orElse(0));
                
            stats.setFailCount(Optional.ofNullable(loginStats.get("fail_count"))
                .map(num -> ((Number) num).intValue())
                .orElse(0));
            
            // 计算成功率，避免除以零
            int totalCount = stats.getSuccessCount() + stats.getFailCount();
            double successRate = totalCount > 0 ? (stats.getSuccessCount() * 100.0 / totalCount) : 0.0;
            stats.setSuccessRate(successRate);
            
            // 平均在线时长（分钟）
            stats.setAvgDuration(Optional.ofNullable(loginStats.get("avg_duration"))
                .map(num -> ((Number) num).doubleValue())
                .orElse(0.0));
                
            stats.setPeakHour(Optional.ofNullable(loginStats.get("peak_hour"))
                .map(num -> ((Number) num).intValue())
                .orElse(0));
        } else {
            // 如果没有统计数据，设置默认值
            stats.setTotalLogins(0);
            stats.setUniqueUsers(0);
            stats.setSuccessCount(0);
            stats.setFailCount(0);
            stats.setSuccessRate(0.0);
            stats.setAvgDuration(0.0);
            stats.setPeakHour(0);
        }
        
        // 6. 计算用户和预约趋势（与上周比较）
        LocalDate lastWeekStart = startDate.minusWeeks(1);
        LocalDate lastWeekEnd = endDate.minusWeeks(1);
        
        // 计算用户增长趋势
        Long lastWeekUsers = userMapper.selectCount(new LambdaQueryWrapper<SysUser>()
            .le(SysUser::getCreateTime, lastWeekEnd.atTime(23, 59, 59)));
        Long currentUsers = userMapper.selectCount(new LambdaQueryWrapper<SysUser>()
            .le(SysUser::getCreateTime, endDate.atTime(23, 59, 59)));
            
        lastWeekUsers = lastWeekUsers != null ? lastWeekUsers : 0L;
        currentUsers = currentUsers != null ? currentUsers : 0L;
        int userTrend = lastWeekUsers == 0 ? 0 : (int) ((currentUsers - lastWeekUsers) * 100.0 / lastWeekUsers);
        stats.setUserTrend(userTrend);
        
        // 计算预约增长趋势
        Long lastWeekAppointments = appointmentMapper.selectCount(new LambdaQueryWrapper<Appointment>()
            .between(Appointment::getAppointmentTime, 
                    lastWeekStart.atStartOfDay(), 
                    lastWeekEnd.atTime(23, 59, 59)));
        Long currentAppointments = appointmentMapper.selectCount(new LambdaQueryWrapper<Appointment>()
            .between(Appointment::getAppointmentTime, 
                    startDate.atStartOfDay(), 
                    endDate.atTime(23, 59, 59)));
                    
        lastWeekAppointments = lastWeekAppointments != null ? lastWeekAppointments : 0L;
        currentAppointments = currentAppointments != null ? currentAppointments : 0L;
        int appointmentTrend = lastWeekAppointments == 0 ? 0 : (int) ((currentAppointments - lastWeekAppointments) * 100.0 / lastWeekAppointments);
        stats.setAppointmentTrend(appointmentTrend);
        
        stats.setStatTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        
        return stats;
    }

    @Override
    public List<UserActiveVO> getActiveUsers(String timeRange) {
        LocalDateTime startTime;
        LocalDateTime endTime = LocalDateTime.now();
        
        // 根据时间范围计算起始时间
        switch (timeRange.toLowerCase()) {
            case "week":
                startTime = endTime.minusWeeks(1);
                break;
            case "month":
                startTime = endTime.minusMonths(1);
                break;
            case "year":
                startTime = endTime.minusYears(1);
                break;
            default:
                startTime = endTime.minusDays(1);
        }
        
        // 查询活跃用户数据
        List<Map<String, Object>> activeUserStats = loginLogMapper.selectActiveUsers(startTime, endTime);
        
        // 转换为VO对象
        return activeUserStats.stream().map(stat -> {
            UserActiveVO vo = new UserActiveVO();
            vo.setUsername((String) stat.get("username"));
            vo.setLoginCount(((Number) stat.get("login_count")).intValue());
            vo.setLastLoginTime(((LocalDateTime) stat.get("last_login"))
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public List<TimeDistributionVO> getLoginTimeDistribution(LocalDate date) {
        LocalDateTime startTime = date.atStartOfDay();
        LocalDateTime endTime = date.atTime(23, 59, 59);
        
        // 查询每小时的登录分布
        List<Map<String, Object>> hourlyStats = loginLogMapper.selectHourlyStats(startTime, endTime);
        
        // 转换为24小时完整数据
        List<TimeDistributionVO> distribution = new ArrayList<>();
        for (int hour = 0; hour < 24; hour++) {
            TimeDistributionVO vo = new TimeDistributionVO();
            vo.setHour(hour);
            
            // 查找当前小时的统计数据
            int finalHour = hour;
            Optional<Map<String, Object>> hourStat = hourlyStats.stream()
                .filter(stat -> ((Number) stat.get("hour")).intValue() == finalHour)
                .findFirst();
            
            vo.setCount(hourStat.map(stat -> ((Number) stat.get("login_count")).intValue())
                .orElse(0));
            vo.setUserCount(hourStat.map(stat -> ((Number) stat.get("user_count")).intValue())
                .orElse(0));
            vo.setAvgDuration(hourStat.map(stat -> ((Number) stat.get("avg_duration")).doubleValue())
                .orElse(0.0));
            
            distribution.add(vo);
        }
        
        return distribution;
    }

    @Override
    public List<Map<String, Object>> getLoginGeoDistribution() {
        Map<String, Integer> result = loginLogMapper.selectGeoDistribution();
        if (result == null) {
            return new ArrayList<>();
        }
        return result.entrySet().stream()
                .map(entry -> {
                    Map<String, Object> converted = new HashMap<>();
                    converted.put("name", entry.getKey());
                    converted.put("value", entry.getValue());
                    return converted;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getDeviceDistribution() {
        Map<String, Integer> result = loginLogMapper.selectDeviceDistribution();
        if (result == null) {
            return new ArrayList<>();
        }
        return result.entrySet().stream()
                .map(entry -> {
                    Map<String, Object> converted = new HashMap<>();
                    converted.put("name", entry.getKey());
                    converted.put("value", entry.getValue());
                    return converted;
                })
                .collect(Collectors.toList());
    }

    /**
     * 更新平均在线时长
     */
    public void updateAvgDuration(LocalDateTime hourStart) {
        try {
            // 计算该小时内的平均在线时长
            Double avgDuration = loginLogMapper.selectOne(
                new LambdaQueryWrapper<SysLoginLog>()
                    .select(SysLoginLog::getLoginDuration)
                    .between(SysLoginLog::getCreateTime, hourStart, hourStart.plusHours(1))
                    .isNotNull(SysLoginLog::getLogoutTime)
            ).getLoginDuration().doubleValue();

            if (avgDuration != null) {
                // 更新统计记录的平均在线时长
                loginStatsMapper.update(null,
                    new LambdaUpdateWrapper<SysLoginStats>()
                        .eq(SysLoginStats::getStatDate, hourStart)
                        .set(SysLoginStats::getAvgDuration, avgDuration.intValue())
                );
            }
        } catch (Exception e) {
            log.error("更新平均在线时长失败: hourStart={}, error={}", 
                hourStart, e.getMessage(), e);
        }
    }
} 